package com.swu.pad.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.huaban.analysis.jieba.JiebaSegmenter;

import weka.classifiers.Classifier;
import weka.core.Attribute;
import weka.core.DenseInstance;
import weka.core.Instance;
import weka.core.Instances;

public class SentenceToClassUtil {
	    //jieba分词工具
		public static JiebaSegmenter jbSeg = new JiebaSegmenter();
		//当前类对象
		public static DocToSentencesClassUtil dtscu=new DocToSentencesClassUtil();
		//保留两位小数
		public static  DecimalFormat df = new DecimalFormat("#.00");
		
		
		
		/*
		 * 传入句子  输出 句子  和 类别
		 */
		public static List<Map<String,Object>> sentenceToClass(String senText)throws Exception {
			String sentenceNoNull=repalceSentenceNone(senText);//1句子去空
			Map<String,Object> sentenceCutwords=cutSentence(sentenceNoNull);//2分词 去停止词
			Map<String,Object> sentenceFesCount=countFeNum(sentenceCutwords);//3 统计 所有 词语 特征相对频率
			Map<String,Object> sentenceInstance=makeInstances(sentenceFesCount);//4根据所有句子频率 ，lc特征构建待预测数据集
			Map<String,Object> sentencesClass=classifyInstance(sentenceInstance);//5预测句子类别
			return null;
		}
		
		
			
		/*
		 * 传入句子     对句子 去空
		 */
		public static String repalceSentenceNone(String senText)throws Exception {
			    //1  去空格 回车 换行 制表符
			    Pattern p = Pattern.compile("\\s*|\t|\r|\n");
			    Matcher m = p.matcher(senText);
			    senText = m.replaceAll("");
			    return senText;
		}
		
		/*
		 * 传入 没有空的句子     对句子 去停止词   ，分词
		 */
		public static Map<String,Object> cutSentence(String senceNoNull)throws Exception {
			Map<String,Object> results=new HashMap<String, Object>();
			//1获取停止词列表
			String stpwordFile=readToString(dtscu.getClass().getResource("/sentenceClass/stpwords.txt").getPath());
			//2 提取所有停止词
		    String[] stpwords=stpwordFile.split("\r\n");
		    List<String> stpwds=new ArrayList<String>();
			for (int i = 0; i < stpwords.length; i++) {
				stpwds.add(stpwords[i]);//构建停止词list
			}
			//3分词		
		   results.put("sentence",senceNoNull);
		   List<String> cutSentence = jbSeg.sentenceProcess(senceNoNull);
		   cutSentence.removeAll(stpwds);
		   results.put("nostpSentence", cutSentence);//去停止词
		   return results;
		}
		
		/*
		 * 传入句子  分词 数组统计  输出 句子，分词 特征统计 
		 */
		public static Map<String,Object> countFeNum(Map<String,Object> cutSentenses)throws Exception {
			Map<String,Object> ctResults=new HashMap<String,Object>();
			//1取静态文件
			String lc=readToString(dtscu.getClass().getResource("/sentenceClass/lcindex.txt").getPath());
			String[] lcs=lc.split("\r\n");//lc 索引   数组 是有序的，按照读取顺序排列
			String lcdict=readToString(dtscu.getClass().getResource("/sentenceClass/sc_liwc.dic").getPath());
			String[] lcds=lcdict.split("\r\n");//lc 字典里的所有行
			//存储所有 词   以及 对应序号
			List<String[]> alLcWords=new ArrayList<String[]>();//存储所有lc 词 与 对应类别
			for (int i = 0; i < lcds.length; i++) {
				String[] lsc=lcds[i].split(" ");
				alLcWords.add(lsc);//将liwc字典的每一行 都加入到  一个list 里  。
			}

			   //2遍历句子，统计特征数量
			   ctResults=cutSentenses;//将原来的  句子 ，分词 信息 赋值给新map 后面put上一个新key保存特征数量
			   //构建   特征  字典 key字典数字  value 出现数量
			   List<List<String>> lcIndexAndCount=new ArrayList<List<String>>();//存下标 和 数字
			   for (int j = 0; j < lcs.length; j++) {
					String[] tempsplit=lcs[j].split(",");
					List<String> temps=new ArrayList<String>();
					temps.add(tempsplit[0]);//字典下标
					temps.add("0");
					temps.add(tempsplit[1]);//
					lcIndexAndCount.add(temps);
				}
			   
			    //3 遍历句子  所有 分词 词语
				List<String> nosentence=(List<String>)cutSentenses.get("nostpSentence");
				for (int j = 0; j < nosentence.size(); j++) {  //遍历每个句子的 每个词
					 for (int k = 0; k < alLcWords.size();k++) {
						if (nosentence.get(j).equals(alLcWords.get(k)[0])) {// 一句话中的词 == 字典里某个词时
							for (int m = 0; m < alLcWords.get(k).length; m++) {//遍历当前 字典 行； 词语 数字 数字。。
								if(isInteger(alLcWords.get(k)[m])) {//是数字
									for (int n = 0; n < lcIndexAndCount.size(); n++) {
										if(lcIndexAndCount.get(n).get(0).equals(alLcWords.get(k)[m])) {
											List<String> tempLcIndex=new ArrayList<String>();
										    tempLcIndex.add(lcIndexAndCount.get(n).get(0));//下标
										    tempLcIndex.add(lcIndexAndCount.get(n).get(1));//次数
										    tempLcIndex.add(lcIndexAndCount.get(n).get(2));
											tempLcIndex.set(1,Integer.toString(Integer.parseInt(lcIndexAndCount.get(n).get(1))+1));
											lcIndexAndCount.set(n, tempLcIndex);
										}
									}
								}
							}
						}
					}
				}
				//4  计算 每个句子 每个lc 特征比值
				int tlcv=0;//存放每个 句子的  lc 总数
				for (int lii = 0; lii < lcIndexAndCount.size(); lii++) {
					tlcv=tlcv+Integer.parseInt(lcIndexAndCount.get(lii).get(1));
				}
				for (int lii = 0; lii < lcIndexAndCount.size(); lii++) {
					if ((!lcIndexAndCount.get(lii).get(1).equals("0.0"))&&tlcv!=0.0) {
						double feCount=Double.valueOf(Integer.parseInt(lcIndexAndCount.get(lii).get(1)));		
						lcIndexAndCount.get(lii).set(1,String.format("%.2f",feCount/tlcv));//设置比值
						lcIndexAndCount.get(lii).set(1,Double.toString(Double.valueOf(lcIndexAndCount.get(lii).get(1))*100));
						lcIndexAndCount.get(lii).set(1,lcIndexAndCount.get(lii).get(1).split("\\.")[0]);
					}
					
				}
				
				ctResults.put("lcFeRatio",lcIndexAndCount);//存放 特征数量统计
			return ctResults;
		}
		
		
		/*
		 * 传入句子数组统计   构建  instances数据集 
		 */
		public static Map<String,Object> makeInstances(Map<String,Object> feNums)throws Exception {
			//1 加载静态资源
			String classContent=readToString(dtscu.getClass().getResource("/sentenceClass/classIndex.txt").getPath());
			String[] classCts=classContent.split("\r\n");
			List<List<String>> classIndexAndValues=new ArrayList<List<String>>();//存 句子类别 下标 和 内容 
			for (int i = 0; i < classCts.length; i++) {   
				String[] tempsplit=classCts[i].split(",");
				List<String> temps=new ArrayList<String>();
				temps.add(tempsplit[0]);//字典下标
				temps.add(tempsplit[1]);
				temps.add(tempsplit[2]);//
				classIndexAndValues.add(temps);
			}
			// ----- 构造  特征表 ，加载读取  lc-fe
			String lcFeContent=readToString(dtscu.getClass().getResource("/sentenceClass/lcindex.txt").getPath());
			String[] lcFeCts=lcFeContent.split("\r\n");
			List<List<String>> lcValues=new ArrayList<List<String>>();//存 lc 类别 ，相当于  instance 的 表头 ，也是所有的 
			for (int i = 0; i < lcFeCts.length; i++) {   
				String[] tempsplit=lcFeCts[i].split(",");
				List<String> temps=new ArrayList<String>();
				temps.add(tempsplit[0]);//lcfe下标
				temps.add(tempsplit[1]);//lcfe名称
				lcValues.add(temps);
			}
		    
			//2构建  instances 。相当于存放整篇文章的 数据集，每一行是一个句子 对应的特征表数据
			ArrayList<Attribute> attributes=new ArrayList<Attribute>();//存放所有属性名称  ，第一行数据  ，funct，neg，。。。money，relativ
			List<String> classValues= new ArrayList<String>(); 
			for (int i = 0; i < classIndexAndValues.size(); i++) {//构建 class类别  nominal  ：离散型数据 ，other ，belief。。。
				classValues.add(classIndexAndValues.get(i).get(1));
			}
			Attribute classAttribute = new Attribute("class", classValues); 
			attributes.add(classAttribute);//将class 属性加入到属性列
			for (int i = 0; i < lcValues.size(); i++) {
				Attribute tempAttribute = new Attribute(lcValues.get(i).get(1));//按顺序创建 属性
				attributes.add(tempAttribute);
			}
			//2 遍历 所有句子  构建  instance
			Instances unlabelSentence=new Instances("sentenceFes",attributes,0);
			unlabelSentence.setClassIndex(0);//设置 0 列是class列
				//map key  sentence   nostpSentence    lcFeRatio
				Map<String,Object> tempMap=feNums;//取出原始 数据 map  ，最后add instance实例
				List<List<String>> lcRatiols=(List<List<String>>) tempMap.get("lcFeRatio");
				Instance instance=new DenseInstance(unlabelSentence.numAttributes());//创建实例，属性数量等于 unlabel句子属性数量
				for (int j = 0; j < lcRatiols.size(); j++) {
					for (int k = 0; k < attributes.size(); k++) {
						if (attributes.get(k).name().equals(lcRatiols.get(j).get(2))) {//相等了
							//如果属性名称对应了，那么就将 对应的 属性   值  赋值
							instance.setValue(attributes.get(k),Double.valueOf(lcRatiols.get(j).get(1)));
						}
					}
				}// 一个句子的   所有属性 被赋值完毕  将其加入到 instances  实例数据 集合 中
				instance.setDataset(unlabelSentence);//所有的instance创建完成后都要设置 归属的 dataset，也就是instances数据集，好对应属性。class的类别 
				feNums.put("instance",instance);
				unlabelSentence.add(instance);
	            //构造数据集  end	
			return feNums;
		}
		
		/*
		 * 传入句子 instance ， 对句子进行分类 
		 */
		public static Map<String,Object> classifyInstance(Map<String,Object> unlabelInstance)throws Exception {
			//1 获取分类器实例
			 List<Map<String,Object>> ctResList=new ArrayList<Map<String,Object>>();
			 Classifier cfer= (Classifier) weka.core.SerializationHelper.read("C:\\RandomForest.model"); 
			//2获取 label对应的 index
			 String classContent=readToString(dtscu.getClass().getResource("/sentenceClass/classIndex.txt").getPath());
			 String[] classCts=classContent.split("\r\n");
			 List<List<String>> classIndexAndValues=new ArrayList<List<String>>();//存 句子   类别 下标 和 名称 
			 for (int i = 0; i < classCts.length; i++) {   
					String[] tempsplit=classCts[i].split(",");
					List<String> temps=new ArrayList<String>();
					if (i==0) {
						temps.add(tempsplit[0].substring(1));//class 的 index double值  ,!utf-8 第一个字符为  空字符 需要 分割一下，取第二个 有数值的子字符串	
					}else {
						temps.add(tempsplit[0]);//不是第一行，正常添加
					}
					temps.add(tempsplit[1]);//class 的 英文名称
					temps.add(tempsplit[2]);//class 的中文名称
					classIndexAndValues.add(temps);
			 }
			 //2遍历句子 分类
			 //map key  sentence  instance:对此分类    nostpSentence    lcFeRatio
			 Instance instance=(Instance) unlabelInstance.get("instance");	//取出原始 数据 map  ，最后add instance 的类别
			 double classValue=cfer.classifyInstance(instance);
			 String classIndex=Double.toString(classValue).split("\\.")[0];
			 String sentenceClass="";//存放句子类别  中文 
			 for (int j = 0; j <classIndexAndValues.size(); j++) {
				if (classIndex.equals(classIndexAndValues.get(j).get(0))) {
					sentenceClass=classIndexAndValues.get(j).get(2);//中文 类别名称
				}
			 }
//			 System.out.println(sentenceClass+"--->"+unlabelInstance.get("sentence").toString());
//			 unlabelInstance.put("class",sentenceClass);
//			 System.out.println(unlabelInstance.toString());
			 
			 
			return unlabelInstance;
		}
		
		
		
		
		
		
		
		
		public static String readToString(String fileName) {  
	        String encoding = "UTF-8";  
	        File file = new File(fileName);  
	        Long filelength = file.length();  
	        byte[] filecontent = new byte[filelength.intValue()];  
	        try {  
	            FileInputStream in = new FileInputStream(file);  
	            in.read(filecontent);
	            in.close();  
	        } catch (FileNotFoundException e) {  
	            e.printStackTrace();  
	        } catch (IOException e) {  
	            e.printStackTrace();  
	        }  
	        try {  
	            return new String(filecontent, encoding);  
	        } catch (UnsupportedEncodingException e) {  
	            System.err.println("The OS does not support " + encoding);  
	            e.printStackTrace();  
	            return null;  
	        }  
	    }
		  //判断是字符串是否为数字
		 public static boolean isInteger(String str) {  
		        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
		        return pattern.matcher(str).matches();  
		  }
		
		
		
		
		
		
}
